package cn.huaqingcheng.tianshu.common.core;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.json.JsonWriteFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;

import java.util.List;

/**
 * JsonTool
 */
public interface JsonTool {

    ObjectMapper OM = newObjectMapper();

    private static JsonMapper newObjectMapper() {
        return JsonMapper.builder()
                .addModule(new JavaTimeModule())
                // 读取: 宽松风格, 接近 json5
                .enable(
                        JsonReadFeature.ALLOW_JAVA_COMMENTS,/* 允许 C 类型注释 */
                        JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES, /* 允许不带引号的字段名 */
                        JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS, /* 允许控制字符 */
                        JsonReadFeature.ALLOW_TRAILING_COMMA /* 允许尾随逗号 */
                )
                // 写出
                .enable(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS  /* 将数字写为字符串 */)
                // 映射器
                .enable(
                        MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, /* 接受不区分大小写的属性 */
                        // MapperFeature.USE_STD_BEAN_NAMING,
                        MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS /* 接受不区分大小写的枚举名 */
                )
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES /* 忽略未知属性 */)
                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS /* 找不到访问器不失败 */)
                .build();
    }

    static String toJson(Object o) {
        if (o == null) {
            return "";
        }
        try {
            return OM.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    static <T> T parse(String json, Class<T> tClass) {
        if (json == null || json.isEmpty()) {
            return null;
        }
        try {
            return OM.readValue(json, tClass);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    static <E> List<E> parseList(String json, Class<E> type) {
        if (json == null || json.isEmpty()) {
            return List.of();
        }
        try {
            return OM.readValue(json, new TypeReference<>() {});
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    static <E, C extends List<E>> C parseList(String json, TypeReference<C> typeRef) {
        if (json == null || json.isEmpty()) {
            try {
                return OM.readValue("[]", typeRef);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }

        try {
            return OM.readValue(json, typeRef);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    static <T> T copy(Object source, Class<T> type) {
        return JsonTool.parse(JsonTool.toJson(source), type);
    }

}
